<script setup>
import { ref, reactive, computed } from 'vue'
import { ElMessage, ElLoading } from 'element-plus'
import { Upload, InfoFilled, Delete } from '@element-plus/icons-vue'
import { analyzeImage as apiAnalyzeImage } from './services/api'

// 图像数据
const imageUrl = ref('')
const imageFile = ref(null)

// 识别结果
const recognitionResult = ref(null)
const loading = ref(false)

// 分类类型
const classificationType = ref('')

// 分类对应的提示词
const classificationPrompts = {
  general: '请详细描述这张图片中的内容，包括可见的物体、人物、场景和任何值得注意的细节。',
  fruit: `你是一个专业的水果识别引擎，负责分析用户上传的水果图片，判断水果种类并提供详细信息。请按照以下要求输出：
1. 识别水果种类（如苹果、香蕉等）
2. 详细描述识别依据，每个判断点单独一行：
   1. 水果的外观特征（颜色、形状、纹理等）
   2. 可能的成熟度判断
   3. 其他显著特征
3. 若无法识别，说明具体原因
4. 输出格式：
{
  "result": "水果名称或'无法识别'",
  "extraInfo": "1. 外观特征描述<br/>2. 成熟度判断<br/>3. 其他特征说明",
  "state": "true/false"
}`,
  garbage: `你是一个专业的智能垃圾分类识别引擎，负责分析用户上传的垃圾图片，判断其所属的垃圾分类类型（厨余垃圾、有害垃圾、其他垃圾、可回收垃圾）。请按照以下要求输出：
1. 判断垃圾类型（四选一）
2. 详细说明分类依据，每个判断点单独一行：
   1. 材料组成分析
   2. 处理方式建议
   3. 环保影响说明
3. 若无法识别，说明具体原因
4. 输出格式：
{
  "result": "垃圾类型或'无法识别'",
  "extraInfo": "1. 材料组成<br/>2. 处理建议<br/>3. 环境影响",
  "state": "true/false"
}`
}

// 格式化AI返回的结果
const formattedResult = computed(() => {
  if (!recognitionResult.value || !recognitionResult.value.result) return '';

  // 如果是水果或垃圾识别，尝试解析JSON
  if (classificationType.value === 'fruit' || classificationType.value === 'garbage') {
    try {
      const data = typeof recognitionResult.value.result === 'string' 
        ? JSON.parse(recognitionResult.value.result)
        : recognitionResult.value.result;
      
      if (!data.state) {
        return `<div class="error-message">识别失败: <br/>${data.extraInfo || '未知错误'}</div>`;
      }

      const typeName = classificationType.value === 'fruit' ? '水果' : '垃圾';
      return `
        <div class="result-card">
          <h3 class="result-title">识别结果</h3>
          <div class="result-field">
            <span class="field-label">${typeName}类型:</span>
            <span class="field-value">${data.result}</span>
          </div>
          <div class="result-field">
            <span class="field-label">分析依据:</span>
            <span class="field-value"><br/>${data.extraInfo}</span>
          </div>
        </div>
      `;
    } catch (e) {
      console.error('JSON解析错误:', e);
    }
  }

  // 通用识别的原始处理逻辑
  let text = recognitionResult.value.result;
  text = text.replace(/^#+\s+(.*?)$/gm, '<h3 class="result-title">$1</h3>');
  text = text.replace(/^---+$/gm, '<hr class="result-divider">');
  text = text.replace(/^(\d+)\.\s+(.*?)$/gm, '<div class="result-list-item"><span class="result-list-number">$1.</span> $2</div>');
  text = text.replace(/^-\s+(.*?)$/gm, '<div class="result-list-item"><span class="result-list-bullet">•</span> $1</div>');
  text = text.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');

  const paragraphs = text.split('\n\n');
  return paragraphs.map(p => {
    if (p.trim() === '') return '';
    if (p.startsWith('<h3') || p.startsWith('<div') || p.startsWith('<hr')) return p;
    return `<p class="result-paragraph">${p}</p>`;
  }).join('');
})

// 上传图像
const handleImageUpload = (event) => {
  const file = event.target.files[0]
  if (!file) return

  // 验证文件类型
  const isImage = file.type.startsWith('image/')
  if (!isImage) {
    ElMessage.error('请上传图片文件')
    return
  }

  imageFile.value = file

  // 创建预览URL
  imageUrl.value = URL.createObjectURL(file)
}

// 发送图像到通义千问API进行识别
const analyzeImage = async () => {
  if (!imageFile.value) {
    ElMessage.warning('请先上传图像')
    return
  }

  loading.value = true
  const loadingInstance = ElLoading.service({
    fullscreen: true,
    text: '正在分析图像...'
  })

  try {
    // 调用API服务进行图像分析
    const result = await apiAnalyzeImage(imageFile.value, {
      model: "qwen-vl-max", // 使用通义千问视觉大模型
      prompt: classificationPrompts[classificationType.value],
      systemPrompt: classificationType.value === 'general'
        ? "你是一个专业的图像分析助手，能够详细描述图像内容并提供深入分析。"
        : classificationType.value === 'fruit'
          ? `你是一个高精度水果识别系统，需遵守以下规则：
1. 识别图片中的水果种类（如苹果、香蕉等）
2. 若无法识别，返回state:false
3. 输出格式：
{
  "result": "水果名称或'无法识别'",
  "extraInfo": "识别依据或失败原因",
  "state": "true/false"
}`
          : `你是一个智能垃圾分类系统，需遵守以下规则：
1. 将垃圾分为：厨余垃圾、有害垃圾、其他垃圾、可回收垃圾
2. 若无法识别，返回state:false
3. 输出格式：
{
  "result": "垃圾类型或'无法识别'",
  "extraInfo": "分类依据或失败原因",
  "state": "true/false"
}`
    })

    recognitionResult.value = result
    ElMessage.success('图像分析完成')
  } catch (error) {
    console.error('图像分析失败:', error)
    ElMessage.error(`分析失败: ${error.message || '未知错误'}`)
    recognitionResult.value = null
  } finally {
    loadingInstance.close()
    loading.value = false
  }
}

// 处理分类按钮点击
const handleClassificationClick = (type) => {
  classificationType.value = type
  // 清空上一次的识别结果
  recognitionResult.value = null
  analyzeImage()
}

// 清除当前图像和结果
const clearAll = () => {
  imageUrl.value = ''
  imageFile.value = null
  recognitionResult.value = null

  // 清除文件输入框的值，允许重新上传相同的文件
  const fileInput = document.getElementById('image-upload')
  if (fileInput) fileInput.value = ''
}
</script>

<template>
  <div class="app-container">
    <header class="app-header">
      <div class="header-content">
        <h1>基于深度学习的图像识别与分类系统</h1>
      </div>
    </header>
    <div class="classification-options">
      <el-button 
        type="primary" 
        size="large" 
        :disabled="!imageUrl || loading"
        @click="() => handleClassificationClick('general')"
      >
        通用识别
      </el-button>
      <el-button 
        type="primary" 
        size="large" 
        :disabled="!imageUrl || loading"
        @click="() => handleClassificationClick('fruit')"
      >
        水果分类
      </el-button>
      <el-button 
        type="primary" 
        size="large" 
        :disabled="!imageUrl || loading"
        @click="() => handleClassificationClick('garbage')"
      >
        垃圾分类
      </el-button>
    </div>
    <main class="main-content">

      <!-- 左侧面板：图片上传区域 -->
      <div class="panel left-panel">
        <h2>图像上传</h2>

        <div class="upload-area" :class="{ 'has-image': imageUrl }">
          <div v-if="!imageUrl" class="upload-placeholder">
            <el-icon class="upload-icon">
              <Upload />
            </el-icon>
            <p>点击或拖拽图片到此处上传</p>
            <input type="file" id="image-upload" accept="image/*" @change="handleImageUpload" class="file-input" />
          </div>

          <div v-else class="image-preview" @click="$refs.fileInput.click()">
            <img :src="imageUrl" alt="预览图像" />
            <el-button 
              class="clear-image-btn" 
              type="danger" 
              size="small" 
              circle
              @click.stop="clearAll"
            >
              <el-icon><Delete /></el-icon>
            </el-button>
            <input 
              ref="fileInput"
              type="file" 
              id="image-upload" 
              accept="image/*" 
              @change="handleImageUpload" 
              class="file-input" 
              style="display: none"
            />
          </div>
        </div>

        <div class="upload-hint">
          <p v-if="!imageUrl">请先上传图片</p>
          <p v-else-if="loading">正在分析中...</p>
          <p v-else>系统已经分析图片，点击图片可替换</p>
        </div>
      </div>

      <!-- 右侧面板：识别结果区域 -->
      <div class="panel right-panel">
        <h2>识别结果</h2>

        <div v-if="!recognitionResult" class="no-result">
          <el-icon class="result-icon">
            <InfoFilled />
          </el-icon>
          <p>上传并分析图像后，识别结果将显示在这里</p>
        </div>

        <div v-else class="result-content">
          <div class="result-item">
            <div class="ai-analysis-container">
              <div class="ai-analysis" v-html="formattedResult"></div>
            </div>
          </div>
        </div>
      </div>
    </main>

    <footer class="app-footer">
      <p>© 2025 基于深度学习的图像识别与分类系统</p>
    </footer>
  </div>
</template>

<style scoped>
.app-container {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background-color: #f8f9fe;
}

.app-header {
  background-color: #5e72e4;
  color: white;
  padding: 1rem;
  box-shadow: 0 2px 12px 0 rgba(94, 114, 228, 0.2);
}

.header-content {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
}

.header-logo {
  width: 80px;
  height: 80px;
  border-radius: 12px;
  object-fit: contain;
}

.main-content {
  display: flex;
  flex: 1;
  padding: 1rem;
  gap: 1rem;
}

.classification-options {
  display: flex;
  justify-content: center;
  gap: 1rem;
  margin: 1rem auto;
}

@media (max-width: 768px) {
  .main-content {
    flex-direction: column;
  }
}

.panel {
  flex: 1;
  background-color: white;
  border-radius: 8px;
  padding: 1.5rem;
  box-shadow: 0 2px 12px 0 rgba(94, 114, 228, 0.1);
  display: flex;
  flex-direction: column;
  border: 1px solid #e9ecef;
}

.panel h2 {
  margin-top: 0;
  color: #303133;
  border-bottom: 1px solid #ebeef5;
  padding-bottom: 0.5rem;
  margin-bottom: 1rem;
}

.upload-area {
  flex: 1;
  border: 2px dashed #c0c4cc;
  border-radius: 6px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  overflow: hidden;
  transition: all 0.3s;
  height: 400px;
  margin-bottom: 1rem;
}

.upload-area:hover {
  border-color: #409eff;
}

.upload-area.has-image {
  border-style: solid;
}

.upload-placeholder {
  text-align: center;
  color: #909399;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.upload-icon {
  font-size: 3rem;
  margin-bottom: 1rem;
}

.file-input {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.image-preview {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.image-preview {
  position: relative;
}

.image-preview img {
  max-width: 100%;
  max-height: 300px;
  object-fit: contain;
}

.clear-image-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 10;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.upload-hint {
  text-align: center;
  color: #909399;
  margin: 1rem 0;
}

.action-buttons {
  display: flex;
  justify-content: center;
  gap: 1rem;
}

.no-result {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #909399;
}

.result-icon {
  font-size: 3rem;
  margin-bottom: 1rem;
}

.result-content {
  flex: 1;
}

.result-item {
  margin-bottom: 1.5rem;
}

.result-item h3 {
  margin-top: 0;
  margin-bottom: 0.5rem;
  color: #606266;
}

.ai-analysis-container {
  max-height: 540px;
  overflow: auto;
}

.ai-analysis {
  background-color: #f8f9fe;
  padding: 1rem;
  border-radius: 4px;
  border-left: 4px solid #5e72e4;
  line-height: 1.6;
  font-size: 1rem;
  white-space: normal;
}

.ai-analysis .result-title {
  color: #303133;
  margin: 1.2rem 0 0.8rem;
  font-weight: 600;
  font-size: 1.2rem;
  border-bottom: 1px solid #ebeef5;
  padding-bottom: 0.5rem;
}

.ai-analysis .result-title:first-child {
  margin-top: 0;
}

.ai-analysis .result-paragraph {
  margin: 0.8rem 0;
  text-align: justify;
}

.ai-analysis .result-divider {
  border: 0;
  border-top: 1px solid #ebeef5;
  margin: 1rem 0;
}

.ai-analysis .result-list-item {
  margin: 0.5rem 0;
  padding-left: 1.5rem;
  position: relative;
}

.ai-analysis .result-list-number,
.ai-analysis .result-list-bullet {
  position: absolute;
  left: 0;
  color: #5e72e4;
  font-weight: bold;
}

.ai-analysis strong {
  color: #303133;
  font-weight: 600;
}

.json-view {
  background-color: #f5f7fa;
  padding: 1rem;
  border-radius: 4px;
  overflow: auto;
  max-height: 400px;
  font-family: monospace;
  white-space: pre-wrap;
}

.app-footer {
  background-color: #5e72e4;
  color: white;
  text-align: center;
  padding: 1rem;
  margin-top: auto;
}
</style>